layui.define(['jquery', 'exconfig', 'layer', 'table'], function(exports) {
	var $ = layui.$,
		exconfig = layui.exconfig,
		layer = layui.layer,
		table = layui.table,
		exutil = {};


	function encode(s, isRaw) {
		return isRaw ? s : encodeURIComponent(s);
	}

	function decode(s, isRaw) {
		return isRaw ? s : decodeURIComponent(s);
	}

	/**
	 * ############################ cookie ############################
	 */
	function stringifyCookieValue(value, isJson) {
		return encode(isJson ? JSON.stringify(value) : String(value));
	}

	//设置cookie方法
	//options Object (expires, path, isRaw, isJson)
	exutil.setCookie = function(key, val, options) {

		var date = new Date(), //获取当前时间
			options = options || {},
			isRaw = (options.isRaw) || true,
			isJson = options.isJson || false,
			expires = options.expires || 0, //单位:小时
			path = options.path || '/';

		if (expires) {
			date.setTime(date.getTime() + expires * 60 * 60 * 1000); //格式化为cookie识别的时间(小时)
		}

		document.cookie = [
			encode(key, isRaw), '=', stringifyCookieValue(val, isJson),
			expires ? ';expires=' + date.toGMTString() : '',
			path ? ';path=' + path : ''
		].join('');

	};

	//获取cookie方法
	exutil.getCookie = function(key, isRaw) {
		/*获取cookie参数*/
		var cookies = document.cookie,
			isRaw = isRaw || true;
		var list = cookies.split("; "); // 解析出名/值对列表
		for (var i = 0; i < list.length; i++) {
			var arr = list[i].split("="); // 解析出名和值
			if (arr[0] == encode(key, isRaw))
				return decode(arr[1], false); // 对cookie值解码
		}
		return "";
	};

	//删除cookie方法
	exutil.delCookie = function(key, path, isRaw) {
		var date = new Date(), //获取当前时间
			path = path || '/',
			isRaw = isRaw || true;
		date.setTime(date.getTime() - 10000); //将date设置为过去的时间
		document.cookie = encode(key, isRaw) + "=v; expires =" + date.toGMTString() + ";path=" + path;
	}

	//清除所有cookie
	exutil.clearCookie = function() {
		var keys = document.cookie.match(/[^ =;]+(?=\=)/g),
			date = new Date();

		date.setTime(date.getTime() - 10000);
		if (keys) {
			for (var i = keys.length; i--;) {
				document.cookie = keys[i] + '=0;path=/;expires=' + date.toGMTString(); //清除当前域名下的,例如：m.kevis.com
				document.cookie = keys[i] + '=0;path=/;domain=' + document.domain + ';expires=' + date.toGMTString(); //清除当前域名下的，例如 .m.kevis.com
				document.cookie = keys[i] + '=0;path=/;domain=kevis.com;expires=' + date.toGMTString(); //清除一级域名下的或指定的，例如 .kevis.com
			}
		}
	}

	/**
	 * ############################ ajax ############################
	 */

	/**
	 * @param {String} url
	 * @param {String} type
	 * @param {Object} opts  
	 * 
	 * opts中的参数：
	 * 1、showLoading  是否显示加载窗 true代表显示(默认)，false代表不显示
	 * 2、data  请求参数，类型String或Object
	 * 3、contentType  请求内容类型  默认是www，如果是json，可修改为application/json
	 * 4、queryString  Object/String 在post请求方式中 需要在url中传递参数时使用
	 */
	exutil._ajax = function(url, type, opts) {
		var loading = null,
			def = $.Deferred(),
			token = exutil.getCookie(exconfig.tokenKey),
			defaultOpts = {
				timeout: 30000,
				headers: {},
				contentType: 'application/json',
				dataType: 'json',
				cache: false
			};

		opts = $.isPlainObject(opts) ? opts : {};
		opts.showLoading = opts.showLoading || true;
		// 打开遮罩层
		if (opts.showLoading) {
			loading = exutil.showLoading("正在加载中...");
		}

		// 设置token
		if (token) {
			defaultOpts.headers[exconfig.tokenKey] = token;
		}

		// 预处理type
		if (typeof(type) === 'string' && type !== '') {
			defaultOpts.type = type;
		} else {
			defaultOpts.type = 'GET';
		}

		// 预处理url
		if (typeof(url) !== 'string' || url === '') {
			throw new Error("url参数不正确");
		} else if (defaultOpts.type === "POST" && opts.queryString) {
			var qString = [],
				qs = '';

			if ($.isPlainObject(opts.queryString)) {
				$.each(opts.queryString, function(k, v) {
					qString.push(k + "=" + String(v))
				});
				qs = qString.join("&");
			}

			if (typeof(opts.queryString) === 'string') {
				qs = opts.queryString
			}

			if (url.indexOf('?') !== -1) {
				defaultOpts.url = url + '&' + qs;
			} else {
				defaultOpts.url = url + '?' + qs;
			}
		} else {
			defaultOpts.url = url;
		}

		// 预处理opts
		if (opts.contentType) {
			if (typeof(opts.contentType) === 'string') {
				defaultOpts.contentType = opts.contentType;
			} else {
				throw new Error("contentType参数不正确");
			}
		}

		// 处理IE8请求使用缓存问题
		if (opts.data) {
			if ($.isPlainObject(opts.data)) {
				// 处理IE8 请求缓存问题
				// opts.data._rd = new Date().getTime();
				defaultOpts.data = defaultOpts.contentType == 'application/json' ? JSON.stringify(opts.data) : opts.data;
			} else if (typeof(opts.data) === 'string') {
				defaultOpts.data = opts.data;
			} else if($.isArray(opts.data)){
				defaultOpts.data = JSON.stringify(opts.data);
			} else {
				throw new Error("data参数不正确");
			}
		}

		defaultOpts = $.extend(true, opts, defaultOpts);

		// 统一异常处理
		def.fail(function(error) {
			if (!error) {
				return;
			}

			if (error.status >= 500) {
				exutil.msg("系统内部错误，请重试");
			} else if (error.status === 403 || error.status === 401) {
				// token过期或未登录
				var exp = /\/modules\/base\/pages\/login\/login.html/i;

				if (exp.test(window.location.pathname)) {
					console.log("匹配");
				} else {
					top.location.replace('/modules/base/pages/login/login.html');
				}

			} else {
				exutil.msg("前端故障，请通知技术人员");
			}
		});

		// 发送请求
		$.ajax(defaultOpts)
			.done(function(resp) {
				if (resp.code === 200 && resp.success) {
					def.resolve(resp.data ? resp.data : '');
				} else {
					exutil.msg(resp.msg);
					def.reject();
				}
			})
			.fail(function(error) {
				def.reject(error);
			})
			.always(function() {
				if (loading) {
					exutil.close(loading);
				}
			});;

		return def;
	}

	/**
	 * GET请求
	 * @param {String} url
	 * @param {Object} opts
	 */
	exutil.get = function(url, opts) {
		opts = opts || {};
		opts.contentType = 'application/x-www-form-urlencoded';
		if (url.substr(0, 7).toLowerCase() == "http://" || url.substr(0, 8).toLowerCase() == "https://") {
			return this._ajax(url, 'GET', opts);
		} else {
			return this._ajax(exconfig.baseUrl() + url, 'GET', opts);
		}
	};

	/**
	 * POST请求
	 * @param {String} url
	 * @param {Object} opts
	 * @param {String} type  参数：body代表application/json类型（默认）  query代表application/x-www-form-urlencoded
	 */
	exutil.post = function(url, opts, type) {
		type = type || 'body';
		opts = opts || {};
		opts.contentType = type == "body" ? 'application/json' : 'application/x-www-form-urlencoded';
		if (url.substr(0, 7).toLowerCase() == "http://" || url.substr(0, 8).toLowerCase() == "https://") {
			return this._ajax(url, 'POST', opts);
		} else {
			return this._ajax(exconfig.baseUrl() + url, 'POST', opts);
		}
	}

	/**
	 * ############################ URL ############################
	 */

	/**
	 * @param {String} name  获取url中查询字符串数据
	 */
	exutil.getUrlParam = function(name) {
		var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
		var r = window.location.search.substr(1).match(reg);
		if (r != null) {
			return decode(r[2]);
		};
		return null;
	}

	/**
	 * @param {String} url
	 * @return {String} result 返回加了随机时间戳的url
	 */
	exutil.addRendomForUrl = function(url) {
		var string = (url !== undefined) ? url : window.location.search;
		var result = string.match(new RegExp("[^\?\&]+=[^\?\&]+", "g"));
		if (!result) {
			result = url + "?_rd=" + new Date().getTime();
		} else {
			var params = {};
			for (var i = 0; i < result.length; i++) {
				var res = result[i].split('=');
				var key = res[0],
					value = res[1];

				if (key === "_rd") {
					params[key] = new Date().getTime();
				} else {
					params[key] = value;
				}
			}

			if (!params._rd) {
				params._rd = new Date().getTime();
			}

			// 查询字符串
			var queryStr = "";

			$.each(params, function(k, v) {
				queryStr += k + '=' + v + '&';
			});


			if (queryStr) {
				queryStr = queryStr.slice(0, url.lastIndexOf('&'));
			}
			result = url.slice(0, url.indexOf('?')) + '?' + queryStr;
		}

		return result;
	}

	/**
	 * 跳转到指定url
	 * @param {String} url
	 */
	exutil.go = function(url) {
		if (typeof(url) === 'string' && url !== '') {
			window.location.href(url);
		}
	}

	/**
	 * 跳转到指定url
	 * @param {String} url
	 */
	exutil.replace = function(url) {
		if (typeof(url) === 'string' && url !== '') {
			window.location.replace(url);
		}
	}

	/**
	 * ############################ 弹窗 ############################
	 */
	/**
	 * 全局打开窗口  默认全局,不支持的话,就局部
	 * @param {Object} options
	 * notice: 
	 * 1.success和cancel事件改为afterSuccess和afterCancel事件
	 * 2.btn2/btn3/...方法里必须写return false;手动调用exutil.close()
	 */
	exutil.open = function(options) {
		var that = this;
		if (!options.zIndex || typeof options.zIndex !== 'number') {
			options.zIndex = window.top.layer ? window.top.layer.zIndex : layer.zIndex;
		}

		options.success = function(layero, index) {
			if (options.afterSuccess && typeof(options.afterSuccess) === 'function') {
				options.afterSuccess(layero, index);
			}
			window.top.layer.setTop(layero);
			var iframeWin = layero.find('iframe')[0]; //得到iframe页的窗口对象，执行iframe页的方法：iframeWin.method();
			window.top.layui.exconfig.wins.push({
				index: index,
				ifrm: iframeWin
			});

		};

		options.cancel = function(index, layero) {
			if (options.afterCancel && typeof(options.afterCancel) === 'function') {
				options.afterCancel(index, layero);
			}
			that.close(index)
			return false;
		}

		if (!window.top.layer) {
			return layer.open(options);
		} else {
			return window.top.layer.open(options);
		}
	}

	/**
	 * 全局提示框  默认全局弹窗,不支持的话,就局部弹窗
	 * @param {string} content
	 * @param {Object} options
	 * @param {function} end
	 */
	exutil.msg = function(content, options, end) {
		if (!window.top.layer) {
			return layer.msg(content, options, end);
		} else {
			return window.top.layer.msg(content, options, end);
		}
	};

	/**
	 * 普通信息框  默认全局弹窗,不支持的话,就局部弹窗
	 * @param {string} content
	 * @param {Object} options
	 * @param {function} yes
	 */
	exutil.alert = function(content, options, yes) {
		if (!window.top.layer) {
			return layer.alert(content, options, yes);
		} else {
			return window.top.layer.alert(content, options, yes);
		}
	};

	/**
	 * @param {String} content
	 * @param {Object} options
	 * @param {Function} yes
	 * @param {Function} cancel
	 */
	exutil.confirm = function(content, options, yes, cancel) {
		if (!window.top.layer) {
			return layer.confirm(content, options, yes, cancel);
		} else {
			return window.top.layer.confirm(content, options, yes, cancel);
		}
	};

	/**
	 * 提示框
	 * @param {Object} content
	 * @param {Object} follow
	 * @param {Object} options
	 */
	exutil.tips = function(content, follow, options) {
		if (!window.top.layer) {
			return layer.tips(content, follow, options);
		} else {
			return window.top.layer.tips(content, follow, options);
		}
	}

	/**
	 * 加载框
	 * @param {String} content
	 */
	exutil.showLoading = function(content) {
		content = content || "加载中...";
		return exutil.msg(content, {
			icon: 16,
			shade: 0.02,
			time: 0
		});
	}

	/**
	 * 关闭指定弹框
	 */
	exutil.close = function(index) {
		var wins;
		if (window != top) {
			wins = window.top.layui.exconfig.wins;
			top.layer.close(index);
		} else {
			wins = window.layui.exconfig.wins;
			layer.close(index);
		}

		var len = wins.length;
		for (var i = 0; i < len; i++) {
			if (wins[i].index === index) {
				wins.splice(i, 1);
				break;
			}
		}
	};

	/**
	 * 关闭所有弹框
	 */
	exutil.closeAll = function() {
		if (window != top) {
			top.layer.closeAll();
			window.top.layui.exconfig.wins = [];
		} else {
			layer.closeAll();
			window.layui.exconfig.wins = [];
		}
	};

	/**
	 * ############################ layui特定交互工具函数 ############################
	 */

	/**
	 * 刷新指定tab页面(默认当前tab)
	 * @param {String} tabId 选填 不填默认当前选中tab
	 */
	exutil.updateTabPage = function(tabId) {
		var currentTabId = tabId || top.layui.exconfig.currentShowMenuKey.join(),
			currentTabPage = $('iframe[data-key="' + currentTabId + '"]', top.document),
			currentTabPageUrl = currentTabPage.prop('src'),
			currentTabPageContent = $('iframe[data-key="' + currentTabId + '"]', top.document).contents(),
			oLoading = currentTabPageContent.find('#main>.layui-tab-content>.layui-show>div');

		oLoading.show();
		currentTabPage.prop('src', this.addRendomForUrl(currentTabPageUrl));
	}

	/**
	 * 刷新指定tab的table(默认当前tab)
	 * @param {String} tableId 必填 刷新的tableId
	 * @param {String} tabId   选填 不填默认当前选中tab
	 * @param {Number} page    选填 table页码,默认是1
	 * @param {Object} where   选填 table条件,默认是{}
	 */
	exutil.updateTabTable = function(tableId, tabId, page, where) {
		var currentTabId = tabId || top.layui.exconfig.currentShowMenuKey.join(),
			currentTabWin = $('iframe[data-key="' + currentTabId + '"]', top.document)[0].contentWindow;

		where = where || {};
		where = $.extend(true, where, {
			"_rd": new Date().getTime()
		});
		page = page || 1;

		currentTabWin.layui.table.reload(tableId, {
			where: where,
			page: {
				curr: page
			}
		});
	}

	/**
	 * 刷新指定弹窗的table(默认当前弹窗)
	 */
	exutil.updateWinTable = function(tableId, winId, page, where) {
		var len = top.layui.exconfig.wins.length,
			currentWin = null;
		
		where = where || {};
		where = $.extend(true, where, {
			"_rd": new Date().getTime()
		});
		page = page || 1;

		if (winId) {
			for (var i = 0; i < len; i++) {
				if (top.layui.exconfig.wins[i].index === winId) {
					currentWin = top.layui.exconfig.wins[i].ifrm.contentWindow;
				}
			}
		} else {
			if(len > 0){
				currentWin = top.layui.exconfig.wins[len - 1].ifrm.contentWindow;
			}
		}
		
		currentWin.layui.table.reload(tableId, {
			where: where,
			page: {
				curr: page
			}
		});
	}

	/**
	 * 刷新指定弹窗页面(默认当前弹窗)
	 * @param {String} winId 选填 不填默认当前弹窗
	 */
	exutil.updateWinPage = function(winId) {
		var len = top.layui.exconfig.wins.length;

		if (winId) {
			for (var i = 0; i < len; i++) {
				if (top.layui.exconfig.wins[i].index === winId) {
					var url = $(top.layui.exconfig.wins[i].ifrm).prop('src');
					$(top.layui.exconfig.wins[i].ifrm).prop('src', this.addRendomForUrl(url));
				}
			}
		} else {
			if (len > 0) {
				var url = $(top.layui.exconfig.wins[len - 1].ifrm).prop('src');
				$(top.layui.exconfig.wins[len - 1].ifrm).prop('src', this.addRendomForUrl(url));
			}
		}
	}

	//输出
	exports('exutil', exutil);
});
